﻿
using NModbus;

using System;
using System.Linq;
using System.Net.Sockets;

/// <summary>
/// Modbus TCP通信客户端
/// </summary>
public class ModbusTcpClient : IDisposable
{
    private readonly TcpClient _tcpClient;
    private readonly IModbusMaster _modbusMaster;
    private readonly byte _slaveId;

    /// <summary>
    /// 初始化Modbus TCP客户端
    /// </summary>
    /// <param name="ip">设备IP地址</param>
    /// <param name="port">端口（默认502）</param>
    /// <param name="slaveId">从站地址</param>
    /// <param name="timeout">超时时间（毫秒）</param>
    public ModbusTcpClient(string ip, int port = 502, byte slaveId = 1, int timeout = 3000)
    {
        _tcpClient = new TcpClient();
        _tcpClient.SendTimeout = timeout;
        _tcpClient.ReceiveTimeout = timeout;
        _tcpClient.Connect(ip, port);
        var factory = new ModbusFactory();
        _modbusMaster = factory.CreateMaster(_tcpClient);
        _slaveId = slaveId;
    }

    #region 读取操作
    // 读取线圈（功能码01）
    public bool[] ReadCoils(ushort startAddr, ushort quantity)
    {
        return _modbusMaster.ReadCoils(_slaveId, startAddr, quantity);
    }

    // 读取保持寄存器（功能码03）
    public ushort[] ReadHoldingRegisters(ushort startAddr, ushort quantity)
    {
        return _modbusMaster.ReadHoldingRegisters(_slaveId, startAddr, quantity);
    }

    // 读取输入寄存器（功能码04）
    public ushort[] ReadInputRegisters(ushort startAddr, ushort quantity)
    {
        return _modbusMaster.ReadInputRegisters(_slaveId, startAddr, quantity);
    }
    #endregion

    #region 写入操作
    // 写入单个线圈（功能码05）
    public void WriteSingleCoil(ushort coilAddr, bool value)
    {
        _modbusMaster.WriteSingleCoil(_slaveId, coilAddr, value);
    }

    // 写入多个线圈（功能码15）
    public void WriteMultipleCoils(ushort startAddr, bool[] values)
    {
        _modbusMaster.WriteMultipleCoils(_slaveId, startAddr, values);
    }

    // 写入单个寄存器（功能码06）
    public void WriteSingleRegister(ushort regAddr, ushort value)
    {
        _modbusMaster.WriteSingleRegister(_slaveId, regAddr, value);
    }

    // 写入多个寄存器（功能码16）
    public void WriteMultipleRegisters(ushort startAddr, ushort[] values)
    {
        _modbusMaster.WriteMultipleRegisters(_slaveId, startAddr, values);
    }
    #endregion

    #region 高级扩展
    // 读取32位浮点数（大端序）
    public float ReadFloat(ushort startAddr)
    {
        var data = ReadHoldingRegisters(startAddr, 2);
        byte[] bytes = {
            (byte)(data[0] >> 8),
            (byte)data[0],
            (byte)(data[1] >> 8),
            (byte)data[1]
        };
        return BitConverter.ToSingle(bytes.Reverse().ToArray(), 0);
    }

    // 写入32位浮点数（大端序）
    public void WriteFloat(ushort startAddr, float value)
    {
        byte[] bytes = BitConverter.GetBytes(value).Reverse().ToArray();
        ushort[] registers = {
            (ushort)((bytes[0] << 8) | bytes[1]),
            (ushort)((bytes[2] << 8) | bytes[3])
        };
        WriteMultipleRegisters(startAddr, registers);
    }
    #endregion

    public void Dispose()
    {
        _modbusMaster?.Dispose();
        _tcpClient?.Close();
        GC.SuppressFinalize(this);
    }
}